import React from 'react';
import {Button, Checkbox, Dropdown, Form, Menu, message, Modal, Popover, Spin, Tree} from 'antd';
import {connect} from 'react-redux';
import {setExpenseTypeSetOfBooks} from 'actions/setting';
import baseService from 'share/base.service';
import errorMessage from 'share/errorMessage';
import 'styles/setting/expense-type/expense-type.scss';
import ExpenseSearchForm
  from 'containers/setting/expense-type/new-expense-type/expense-type-custom/component/expense-search-form';
import NewExpenseType from 'containers/setting/expense-type/new-expense-type/new-expense-type';
import {LanguageInput} from 'components/index';
import ExportModal from 'components/template/export-modal/export-modal';
import Importer from 'components/template/importer';
import {deepFullCopy, messages} from 'share/common';
import expenseTypeService from 'containers/setting/expense-type/expense-type.service';
// images
import defaultExpenseTypeIcon from 'images/expense/default-expense-type.png';
import iconCopy from 'images/setting/expense-type/icon-copy-type.svg';
import iconCopyHover from 'images/setting/expense-type/icon-copy-type-hover.svg';
import iconCopyDisabled from 'images/setting/expense-type/icon-copy-type-disabled.svg';
import iconDelete from 'images/setting/expense-type/icon-delete-type.svg';
import iconDeleteHover from 'images/setting/expense-type/icon-delete-type-hover.svg';
import iconAdd from 'images/setting/expense-type/icon-add-type.svg';
import iconAddHover from 'images/setting/expense-type/icon-add-type-hover.svg';
import iconAddWhite from 'images/setting/expense-type/icon-add-type-white.svg';
import iconAddBlack from 'images/setting/expense-type/icon-add-type-black.svg';
import iconAddCategory from 'images/setting/expense-type/icon-add-category.svg';
import iconImport from 'images/setting/expense-type/icon-import-type.svg';
import iconExport from 'images/setting/expense-type/icon-export-type.svg';
import iconArrowExport from 'images/setting/expense-type/icon-arrow-export.svg';
import iconArrowExportHover from 'images/setting/expense-type/icon-arrow-export-hover.svg';
import iconCategory from 'images/setting/expense-type/icon-category-type.svg';
import iconCategoryOpen from 'images/setting/expense-type/icon-category-type-open.svg';
import iconCategoryShrink from 'images/setting/expense-type/icon-category-shrink.svg';

const FormItem = Form.Item;

const {TreeNode} = Tree;

const {confirm} = Modal;

/**
 * 费用类型配置
 * 左侧树状可拖拽排序 右侧详情信息
 * ??? 有修改的话不允许做其他的操作？～
 */
class ExpenseTypeV2 extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      sourceCategory: [], // 后端返回的费用类型信息
      showCategory: [], // 显示费用类型信息
      expandedKeys: [], // 默认显示的tree页
      ignoreExpandedKeys: false, // 不操作显示的项目信息
      selectedKeys: [], // 选中的的值
      checkedKeys: [], // 复选选中的值
      setOfBooksLoading: false,
      setOfBooks: [],
      loading: false,
      expenseTypeId: '',
      mod: '',
      categoryName: '',
      enableEditCategoryName: true,
      categoryNameI18n: [],
      currentItem: {},
      parentInfo: {},
      batchEnableStatus: false, // 批量启用
      sortCategoryStatus: false,// 是否排序
      copyExpenseStatus: false, // 是否复制
      leftPutWay: false, // 左侧是否收起
      leftPutWayEnd: false, // 左侧是否已经收起
      searchExpense: false, // 搜索栏是否展开
      saveCategoryLoading: false, //保存费用类型状态
      batchEnableLoading: false, //批量启用
      sureSortLoading: false, //排序保存
      query: {},
      checkedAll: false,
      allKeysLength: 0,
      showEnableExpense: false,
      deleteCategoryOIDMap: {},
      hasChanged: false // 全局监听有无修改
    };
    this.expenseTypeRef = null;
    this.cacheHandle = null; // 缓存处理
  }

  componentDidMount() {
    if (!this.props.expenseTypeSetOfBooks.id) {
      this.props.dispatch(setExpenseTypeSetOfBooks({
        expenseTypeLevelCode: this.props.tenant.tenantFormRecommend ? "TENANT" : "SET_OF_BOOK",
        id: this.props.company.setOfBooksId,
        setOfBooksName: this.props.company.setOfBooksName
      }));
    }
    this.initSetOfBooks()
      .then(res => {
        this.getSourceCategory({setOfBooksId: res});
      })
      .catch(error => {
        errorMessage(error.response);
      });
  }

  initSetOfBooks = () => {
    this.setState({setOfBooksLoading: true});
    return new Promise((resolve, reject) => {
      baseService.getSetOfBooksByTenant()
        .then(res => {
          this.setState({setOfBooks: res.data});
          let exitSetOfBooks = false;
          let id = this.props.company.setOfBooksId;
          const expenseTypeLevelCode = this.props.tenant.tenantFormRecommend ? "TENANT" : "SET_OF_BOOK";
          res.data.map(item => {
            if (item.id === (this.props.expenseTypeSetOfBooks.id || this.props.company.setOfBooksId)) {
              exitSetOfBooks = true;
              id = item.id;
              this.props.dispatch(setExpenseTypeSetOfBooks(Object.assign({}, item, { expenseTypeLevelCode })));
            }
          });
          if (!exitSetOfBooks) {
            this.props.dispatch(setExpenseTypeSetOfBooks({
              expenseTypeLevelCode,
              id: this.props.company.setOfBooksId,
              setOfBooksName: this.props.company.setOfBooksName
            }));
          }
          resolve(id);
          this.setState({setOfBooksLoading: false, query: {setOfBooksId: id}});
        })
        .catch(error => {
          reject(error);
          this.setState({setOfBooksLoading: false});
        });
    });
  };
  handleChangeSetOfBooks = (value) => {
    return new Promise((resolve, reject) => {
      if (!value.setOfBooksId) {
        delete value.setOfBooksId;
      }
      let query = {
        companyId: '',
        expenseTypeId: '',
        ...value
      };
      this.validCreated(() => this.handleChangeSetOfBooks(value))
        .then(() => {
          setTimeout(() => this.getSourceCategory(query));
          resolve();
        })
        .catch(reject);
    })
  };
  handlePutAway = (value) => {
    setTimeout(() => {
      this.setState({leftPutWayEnd: value});
    }, 100);
    this.setState({leftPutWay: value});
  };
  handleHide = (value) => {
    this.setState({searchExpense: !value});
  };
  getSourceCategory = (params) => {
    const { expenseTypeLevelCode, id } = this.props.expenseTypeSetOfBooks;
    let query = {...this.state.query, ...{createdManually: null, enabled: null}};
    if (typeof params === 'object') {
      query = {...query, ...params}
    }
    query.levelCode = expenseTypeLevelCode;
    query.setOfBooksId = expenseTypeLevelCode === "TENANT" ? undefined : id;
    this.setState({loading: true, query: query});
    baseService.getExpenseTypesBySetOfBooks(query)
      .then(res => {
        let sourceCategory = res.data.rows;
        this.initShowCategory({sourceCategory, isInit: true});
        this.setState({sourceCategory: sourceCategory});
      });
  };
  // 默认费用大类对象
  getShowCategoryObj = (category = {}) => {
    return {
      title: category.name,
      key: category.id || this.getCurrentKey(),
      id: category.id,
      expenseTypeCategoryOID: category.expenseTypeCategoryOID,
      children: [],
      defaultCategory: category.defaultCategory,
      isCategory: true,
      i18n: category.i18n || {name: []},
      isNewCreate: category.isNewCreate,
      sequence: category.sequence,
      setOfBooksId: category.setOfBooksId,
      tenantId: category.tenantId
    };
  };
  getShowExpenseTypeObj = (expenseType = {}) => {
    return {
      title: expenseType.name,
      key: expenseType.id,
      expenseTypeId: expenseType.id,
      isAbleToCreatedManually: expenseType.isAbleToCreatedManually,
      isNewCreate: expenseType.isNewCreate,
      sequence: expenseType.sequence,
      iconURL: expenseType.iconURL,
      enabled: expenseType.enabled
    };
  };
  /**
   * 初始化前端显示的费用类型信息 只有两层结构可以简单处理
   * sourceCategory 费用类型信息
   * isInit 初始化
   */
  initShowCategory = ({sourceCategory, isInit, changeEnableExpense = false}) => {
    this.setState({loading: true});
    let showCategory = [];
    let expandedKeys = [];
    let {sourceCategory: currentSourceCategory, sortCategoryStatus, ignoreExpandedKeys,
      showEnableExpense, currentItem, batchEnableStatus} = this.state;
    if (isInit) {
      currentSourceCategory = sourceCategory;
    }
    let key;
    let allKeysLength = 0;
    currentSourceCategory.forEach(category => {
      let currentCategory = this.getShowCategoryObj(category);
      (batchEnableStatus || sortCategoryStatus || isInit) && (expandedKeys.push(currentCategory.key));
      category.expenseTypes.forEach(expenseType => {
        if (showEnableExpense || expenseType.enabled || sortCategoryStatus || batchEnableStatus) {
          let currentExpenseType = this.getShowExpenseTypeObj(expenseType);
          currentCategory.children.push(currentExpenseType);
          allKeysLength += 1;
          if (!key) {
            key = currentExpenseType.key;
          }
        }
      });
      showCategory.push(currentCategory);
    });
    let parentInfo = {};
    let currentItemInfo = {};
    if (currentItem.key) {
      let currentInfo = this.getCurrentAndParentInfo(currentItem.key, showCategory);
      parentInfo = currentInfo.parentInfo;
      currentItemInfo = currentInfo.currentItemInfo;
    }

    // 存在值处理
    if (currentItemInfo.key) {
      if (parentInfo.key) {
        !batchEnableStatus && !sortCategoryStatus && (expandedKeys = [parentInfo.key]);
      } else {
        expandedKeys = [];
      }
      key = currentItemInfo.key;
    }
    if (!key && showCategory.length > 0) {
      key = showCategory[0].key;
    }
    if (!changeEnableExpense) {
      if (!this.cacheHandle) {
        this.onSelect([key], showCategory);
      } else {
        this.setState({showCategory}, () => {
          this.setState({ loading: false});
          this.cacheHandle();
          this.cacheHandle = null;
        });
      }
    } else if (changeEnableExpense) {
      // 只是切换显示的话 张开的列不处理
      // 如果有正在编辑及新建的需要正常显示
      let currentItem = deepFullCopy(this.state.currentItem);
      if (currentItem.key && currentItem.isNewCreate) {
        let {currentItemInfo, parentInfo, currentIndex} = this.getCurrentAndParentInfo(currentItem.key, this.state.showCategory);
        // 编辑大类
        if (currentItem.isCategory) {
          showCategory.splice(currentIndex, 0, currentItemInfo);
        } else {
          // 编辑费用类型
          let {currentItemInfo: currentCategory} = this.getCurrentAndParentInfo(parentInfo.key, showCategory);
          currentCategory.children.splice(currentIndex, 0, currentItemInfo);
        }
      }
      expandedKeys = this.state.expandedKeys;
      this.setState({showCategory}, () => {
        this.setState({ loading: false});
        if (this.cacheHandle) {
          this.cacheHandle();
          this.cacheHandle = null;
        }
      });
    }
    if (!ignoreExpandedKeys) {
      this.setState({expandedKeys});
    }
    this.setState({
      ignoreExpandedKeys: false,
      allKeysLength
    });
  };
  handleChangeI18n = (value, i18n, type) => {
    this.setState({
      [type]: value,
      [`${type}I18n`]: i18n,
      hasChanged: true
    });
  };
  onShowEnableChange = (e) => {
    let val = e.target.checked;
    this.setState({showEnableExpense: val}, () => {
      this.initShowCategory({changeEnableExpense: true});
    });
  };
  onCheckedAllChange = (e) => {
    let {showCategory} = this.state;
    let checkedKeys = [];
    let val = e.target.checked;
    if (val) {
      showCategory.forEach(category => {
        checkedKeys.push(category.key);
        category.children.forEach(expense => {
          checkedKeys.push(expense.key);
        })
      })
    }
    this.setState({checkedAll: val, checkedKeys});
  };
  onCheck = (checkedKeys) => {
    this.setState({checkedKeys}, () => {
      let checkedAll = false;
      if (this.state.allKeysLength === this.getValidCheckedKeys(false, true).length) {
        checkedAll = true;
      }
      this.setState({checkedAll});
    });
  };
  onExpand = (expandedKeys) => {
    let showCategory = JSON.parse(JSON.stringify(this.state.showCategory));
    expandedKeys = expandedKeys.filter((key) => {
      return showCategory.some(category => category.key === key);
    });
    this.setState({expandedKeys});
  };
  // 选中处理 返回的是key值 Array
  onSelect = (item, showCategory = []) => {
    // 排序 或者 启用操作时 不做选中处理
    if (this.state.batchEnableStatus || this.state.sortCategoryStatus) {
      if (showCategory.length > 0) {
        this.setState({showCategory}, () => {
          this.setState({loading: false});
        });
      }
      return !1;
    }
    if (item.length < 1) {
      this.setState({loading: false});
      return !1;
    }
    this.validCreated(() => {this.onSelect(item, showCategory)}).then((res) => {
      if (res === 'DELETE_HANDLE') {
        showCategory = JSON.parse(JSON.stringify(this.state.showCategory));
      }
      this.onSelectData(item, showCategory);
    })
  };
  onSelectData = (item, showCategory = []) => {
    if (!Array.isArray(showCategory)) {
      showCategory = this.state.showCategory;
    }
    let {currentItemInfo, parentInfo} = this.getCurrentAndParentInfo(item[0], showCategory);
    let currentItem = currentItemInfo;
    let mod = 'CATEGORY';
    if (!currentItemInfo.isCategory) {
      mod = 'EXPENSE_DETAIL';
    }
    if (mod === 'EXPENSE_DETAIL') {
      let expenseTypeId = currentItem.expenseTypeId;
      // 如果费用id一样 则不需要修改
      if (expenseTypeId === this.state.expenseTypeId && !this.state.copyExpenseStatus) {
        this.setState({mod, currentItem, selectedKeys: item, parentInfo, showCategory}, () => {
          this.setState({loading: false});
        });
        return !1;
      };
      this.setState({
        mod: ''
      }, () => {
        setTimeout(() => {
          this.setState({
            mod, expenseTypeId, currentItem, selectedKeys: item, parentInfo,
            showCategory
          }, () => {
            this.setState({loading: false});
          });
        }, 300);
      });
    } else {
      let categoryName = currentItem.title;
      let categoryNameI18n = [];
      if (currentItem.i18n && currentItem.i18n.name) {
        categoryNameI18n = currentItem.i18n.name;
      }
      let enableEditCategoryName = !currentItem.defaultCategory;
      this.props.form.setFieldsValue({categoryName});
      this.setState({
        showCategory, parentInfo, mod, categoryName, categoryNameI18n,
        currentItem, enableEditCategoryName, selectedKeys: item,
      }, () => {
        this.setState({loading: false});
      });
    }
  };
  // 批量操作默认打开所有树节点
  handleBatchEnable = () => {
    this.setState({batchEnableStatus: true, searchExpense: false}, () => {
      this.initShowCategory({});
    });
  };
  handleBatchEnableExpense = (status = false) => {
    let expenseTypeIds = this.getValidCheckedKeys(!status);
    if (expenseTypeIds.length < 1) {
      let info = messages('expense-6.key278')/*所选费用均已禁用,无需操作*/;
      if (status) {
        info = messages('expense-6.key279')/*所选费用均已启用,无需操作*/;
      }
      message.info(info);
      return !1;
    }
    let title = messages('expense-6.key280')/*您确定要禁用所选的费用类型*/;
    if (status) {
      title = messages('expense-6.key281')/*您确定要启用所选的费用类型*/;
    }
    confirm({
      title: title + '?',
      okText: messages('common.ok')/*确定*/,
      cancelText: messages('common.cancel')/*取消*/,
      onOk: () => {
        let params = {
          enabled: status,
          expenseTypeIds: expenseTypeIds
        };
        this.setState({batchEnableLoading: true});
        expenseTypeService.batchEnableExpenseType(params).then(() => {
          let msg = messages('expense-6.key282',{arg1: expenseTypeIds.length})/*{arg1}个费用类型已禁用*/;
          if (status) {
            msg = messages('expense-6.key283',{arg1: expenseTypeIds.length})/*{arg1}个费用类型已启用*/;
          }
          message.success(msg);
          this.setState({checkedKeys: [], checkedAll: false});
          this.getSourceCategory({});
        }).catch(error => {
          errorMessage(error.response);
        }).finally(() => {
          this.setState({batchEnableLoading: false})
        });
      },
      onCancel: () => {
      },
    });
  };
  getValidCheckedKeys = (status = false, onlyNotCategory= false) => {
    let {showCategory, checkedKeys} = this.state;
    return checkedKeys.filter(key => {
      let {currentItemInfo} = this.getCurrentAndParentInfo(key, showCategory);
      if (onlyNotCategory) {
        return !currentItemInfo.isCategory;
      }
      return currentItemInfo.enabled === status && !currentItemInfo.isCategory;
    });
  };
  cancelBatchEnable = () => {
    this.setState({batchEnableStatus: false, checkedKeys: [], checkedAll: false}, () => {
      this.initShowCategory({});
    });
  };
  // 开始排序
  handleSortCategory = () => {
    this.setState({sortCategoryStatus: true, searchExpense: false}, () => {
      this.initShowCategory({});
    });
  };
  cancelSortHandle = () => {
    this.setState({sortCategoryStatus: false}, () => {
      this.initShowCategory({});
    });
  };
  sureSortHandle = () => {
    let showCategory = JSON.parse(JSON.stringify(this.state.showCategory));
    // 前端优化 对比处理修改的数据 不需要处理所有数据
    let params = showCategory.map((category, index) => {
      let expenseTypes = category.children.map((expense, childrenIndex) => {
        return {
          sequence: childrenIndex,
          expenseTypeCategoryId: category.key,
          id: expense.key
        }
      });
      return {
        id: category.key,
        setOfBooksId: category.setOfBooksId,
        tenantId: category.tenantId,
        sequence: index,
        expenseTypes: expenseTypes
      }
    });
    this.setState({sureSortLoading: true});
    expenseTypeService.sortExpenseTypeV2(params).then(() => {
      message.success(messages('common.operate.success')/*操作成功*/);
      this.setState({sortCategoryStatus: false});
      this.getSourceCategory({});
    }).catch(error => {
      errorMessage(error.response);
    }).finally(() => {
      this.setState({sureSortLoading: false})
    });
  };
  // 拖拽
  onDrop = info => {
    const dropKey = info.node.props.eventKey;
    const dragKey = info.dragNode.props.eventKey;
    const dropPos = info.node.props.pos.split('-');
    const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);

    const data = [...this.state.showCategory];
    let {currentItemInfo: dragObj, currentIndex: dragInd, parentInfo: dragArr} = this.getCurrentAndParentInfo(dragKey, data);
    let {currentItemInfo: dropObj, parentInfo: dropArr} = this.getCurrentAndParentInfo(dropKey, data);

    // 大类不能加到大类下面
    if (dragObj.isCategory && !dropObj.isCategory) {
      return !1;
    }
    // 需要处理的是费用类型
    if (!dragObj.isCategory) {
      dragArr.children.splice(dragInd, 1);
      // 添加到类别下
      if (dropObj.isCategory) {
        dropObj.children = dropObj.children || [];
        dropObj.children.unshift(dragObj);
      } else {
        // 删除操作后序列会发生变化 需要重新获取下
        let {currentIndex: dropInd} = this.getCurrentAndParentInfo(dropKey, data);
        if (dropPosition === -1) {
          dropArr.children.splice(dropInd, 0, dragObj);
        } else {
          dropArr.children.splice(dropInd + 1, 0, dragObj);
        }
      }
    } else {
      dragArr.splice(dragInd, 1);
      // 删除操作后序列会发生变化 需要重新获取下
      let {currentIndex: dropInd} = this.getCurrentAndParentInfo(dropKey, data);
      if (dropPosition === -1) {
        dropArr.splice(dropInd, 0, dragObj);
      } else {
        dropArr.splice(dropInd + 1, 0, dragObj);
      }
    }
    this.setState({
      showCategory: data,
    });
  };
  // 导入
  renderImporter = (putAway = false) => {
    let buttonValue = (<Button className='icon-import-wrap'>
      <img src={iconImport} className='icon-import'/>
    </Button>);
    if (putAway) {
      buttonValue = (<Button className='button-wrap'>
        <img src={iconImport} className='icon-button' alt=''/>
      </Button>);
    }
    let triggerNode = (<Popover content={messages('expense-6.key284')/*导入费用*/}>
      {buttonValue}
    </Popover>);
    return (
      <Importer
        triggerNode={triggerNode}
        modalOptions={{title: messages('expense-6.key210')/*导入费用类型*/}}
        templateOptions={{
          templateList: [{
            templateName: messages('expense-6.key211')/*下载Excel电子表格*/,
            downloadUrl: '/api/expense/type/template/download',
            downFileName: `${messages('common.expense.type')/*费用类型*/}__${new Date().getTime()}`
          }]
        }}
        uploadOptions={{uploadUrl: '/api/expense/type/template/upload', accept: '.xlsx'}}
        errorTableData={this.handelImportCallBack}
        onOk={this.getSourceCategory}
      />
    );
  };
  handelImportCallBack = (result) => {
    let resultDom;
    if (result.success) {
      resultDom = (<div>{messages('expense-6.key207')/*导入成功*/}</div>);
    } else {
      resultDom = (
        <div>
          <div style={{marginBottom: 10}}>
            {messages('expense-6.key208')/*导入失败*/}
          </div>
          {result.rows
            ? <a href={result.rows.fileURL}>{messages('expense-6.key209')/*下载错误文件*/}</a>
            : <span>{result.message}</span>
          }
        </div>
      );
    }
    return resultDom;
  };
  // 导出
  renderExportMenu = () => {
    const {expenseTypeSetOfBooks} = this.props;
    const exportArray = [
      {
        key: 1,
        name: messages('expense-6.key285')/*导出全部类型*/,
        body: {editAble: null, levelCode: 'ALL'}
      }, {
        key: 2,
        name: messages('expense-6.key286')/*导出可导入的类型*/,
        body: {editAble: true, levelCode: 'ALL'}
      }
    ];
    return (
      <Menu>
        {exportArray.map(item => {
          return (
            <Menu.Item key={item.key} style={{textAlign: 'left'}}>
              <ExportModal
                disabled={false}
                codeCheck={true}
                exportTitle={item.name}
                exportType="EXPENSE_TYPE_REPORT"
                exportCondition={item.body}
                exportCommand={'EXPENSE_TYPE_REPORT'}/>
            </Menu.Item>
          );
        })
        }
      </Menu>
    );
  };
  /**
   * 获取当前对象的信息及父类信息
   * @param key 对象唯一识别码
   * @param showCategory
   * @returns {{parentInfo: {}, currentItemInfo: {}, currentIndex: number}}
   */
  getCurrentAndParentInfo = (key, showCategory) => {
    let currentItemInfo = showCategory.length ? {} : { isCategory: true };
    let currentIndex = 0;
    let parentInfo = {};
    for (let i = 0; i < showCategory.length; i++) {
      let currentCategory = showCategory[i];
      if (currentCategory.key === key) {
        currentItemInfo = currentCategory;
        currentIndex = i;
        parentInfo = showCategory;
        break;
      } else if (currentCategory.children && currentCategory.children.length > 0) {
        let temp = false;
        for (let j = 0; j < currentCategory.children.length; j++) {
          if (currentCategory.children[j].key === key) {
            currentItemInfo = currentCategory.children[j];
            temp = true;
            currentIndex = j;
            parentInfo = currentCategory;
            break;
          }
        }
        if (temp) {
          break;
        }
      }
    }
    return {
      currentItemInfo, currentIndex, parentInfo
    };
  };
  /**
   * 添加逻辑处理
   * 1: 大类添加
   *  1: 添加新的大类信息 添加到首项
   *  2: 大类上添加新的大类 添加到当前大类上方
   *  3: 大类上添加新的费用类型 添加到首项
   *
   * 2: 添加费用类型
   *    1: 不存在当前选中的值提示请先选择费用大类
   *    2: 当前选中值为大类 则添加在首页
   *    3：当前选中值为费用类型 则添加在选中值下方
   * @param item
   */
  addHandle = (item) => {
    this.validCreated(() => {this.addHandle(item)}).then(() => {
      this.addDataHandle(item);
    })
  };
  addDataHandle = (item) => {
    let key = this.getCurrentKey();
    const data = JSON.parse(JSON.stringify(this.state.showCategory));
    let expandedKeys = JSON.parse(JSON.stringify(this.state.expandedKeys));
    let currentItem = this.state.currentItem;
    let newExpenseType = this.getShowExpenseTypeObj({isNewCreate: true});
    let newCategory = this.getShowCategoryObj({isNewCreate: true});
    newExpenseType.key = key;
    newCategory.key = key;
    newCategory.sequence = 0;
    newExpenseType.sequence = 0;
    if (item.isCategory) {
      if (!item.key) {
        try {
          newCategory.sequence = data[0].sequence - 1;
        } catch (e) {
        }
        data.unshift(newCategory);
        expandedKeys = [];
      } else {
        let {parentInfo, currentItemInfo, currentIndex} = this.getCurrentAndParentInfo(item.key, data);
        try {
          newCategory.sequence = currentItemInfo.sequence;
        } catch (e) {
        }
        if (expandedKeys.includes(item.key)) {
          expandedKeys.splice(expandedKeys.indexOf(item.key), 1);
        }
        parentInfo.splice(currentIndex, 0, newCategory);
      }
    } else {
      if (item.key) {
        let {parentInfo, currentItemInfo, currentIndex} = this.getCurrentAndParentInfo(item.key, data);
        try {
          newExpenseType.sequence = currentItemInfo.sequence;
        } catch (e) {
        }
        if (!expandedKeys.includes(parentInfo.key)) {
          expandedKeys.push(parentInfo.key);
        }
        parentInfo.children.splice(currentIndex, 0, newExpenseType);
      } else if (currentItem.isCategory) {
        let {currentItemInfo} = this.getCurrentAndParentInfo(currentItem.key, data);
        currentItemInfo.children = currentItemInfo.children || [];
        try {
          newExpenseType.sequence = currentItemInfo.children[0].sequence - 1;
        } catch (e) {
        }
        if (!expandedKeys.includes(currentItem.key)) {
          expandedKeys.push(currentItem.key);
        }
        currentItemInfo.children.unshift(newExpenseType);
      } else {
        let {parentInfo} = this.getCurrentAndParentInfo(currentItem.key, data);
        try {
          newExpenseType.sequence = parentInfo.children[0].sequence - 1;
        } catch (e) {
        }
        if (!expandedKeys.includes(parentInfo.key)) {
          expandedKeys.push(parentInfo.key);
        }
        parentInfo.children && parentInfo.children.unshift(newExpenseType);
      }
    }
    this.setState({expandedKeys});
    this.onSelect([key], data);
    if (this.state.leftPutWayEnd) {
      this.handlePutAway(false);
    }
  };
  // 操作前需要是否存在新建的项目 有则提示 有则中断当前操作
  // 需要记录操作行为 取消的话 删除新建项目继续之前的操作
  validCreated = (fn) => {
    return new Promise((resolve, reject) => {
      let currentItem = this.state.currentItem;
      if (currentItem.isNewCreate || this.state.hasChanged) {
        Modal.confirm({
          title: messages('expense-6.key287')/*您还未保存，保存后才可进行下一步操作*/,
          content: messages('expense-6.key288')/*复原会撤销之前的操作*/,
          okText: messages('expense-6.key289')/*立即保存*/,
          cancelText: messages('expense-6.key290')/*复原*/,
          onOk: () =>  {
            this.cacheHandle = fn;
            if (this.state.mod === 'EXPENSE_DETAIL') {
              this.expenseTypeRef && this.expenseTypeRef.handleSaveCurrentInfo();
            } else {
              this.saveCategoryHandle();
            }
            reject('1');
          },
          onCancel: () => {
            // 如果是新建则需要删除 如果是其他有修改就直接下一步操作
            if (currentItem.isNewCreate) {
              this.deleteDataHandle(currentItem, true);
              this.setState({hasChanged: false}, () => {
                resolve('DELETE_HANDLE');
              });
            } else {
              this.setState({hasChanged: false}, () => {
                resolve('1');
              });
            }
          },
        });
        return !1;
      }
      resolve('1');
    });
  };
  // 前端使用唯一标识
  getCurrentKey = () => {
    return '' + new Date().getTime();
  };
  // 复制处理
  copyHandle = (item) => {
    if (!item.isAbleToCreatedManually) {
      message.warning(messages('expense-6.key2')/*该费用类型不可复制*/);
      return !1;
    }
    this.validCreated(() => {this.copyHandle(item)}).then(() => {
      const data = JSON.parse(JSON.stringify(this.state.showCategory));
      let {parentInfo, currentItemInfo, currentIndex} = this.getCurrentAndParentInfo(item.key, data);
      let newExpense = JSON.parse(JSON.stringify(currentItemInfo));
      let key = this.getCurrentKey();
      newExpense.isNewCreate = true;
      newExpense.key = key;
      parentInfo.children.splice(currentIndex, 0, newExpense);
      this.onSelect([key], data);
      this.setState({copyExpenseStatus: true});
    });
  };
  /**
   * 删除处理
   * 删除大类需要判断是否有费用类型明细 如果有则提示并且不可删除
   * 删除费用类型 则直接删除
   * @param item
   */
  deleteHandle = (item) => {
    if (!item.isNewCreate) {
      this.validCreated(() => {this.deleteHandle(item)}).then(() => {
        this.deleteDataHandle(item);
      })
    } else {
      this.deleteDataHandle(item);
    }
  };
  // 校验时删除的话只需更新数组 后续会由其他操作处理
  deleteDataHandle(item, isValidDelete = false) {
    const data = JSON.parse(JSON.stringify(this.state.showCategory));
    let {parentInfo, currentIndex} = this.getCurrentAndParentInfo(item.key, data);
    let currentItem = {};
    if (parentInfo[currentIndex + 1]) {
      currentItem = parentInfo[currentIndex + 1];
    } else if (parentInfo[currentIndex - 1]) {
      currentItem = parentInfo[currentIndex - 1];
    }
    const successHandle = () => {
      if (item.expenseTypeCategoryOID) {
        this.setState({currentItem, copyExpenseStatus: false}, () => {
          this.getSourceCategory({});
        });
      } else {
        if (item.isCategory) {
          parentInfo.splice(currentIndex, 1);
        } else {
          parentInfo.children.splice(currentIndex, 1);
        }
        let key = currentItem.key;
        if (!key) {
          key = data[0] && data[0].key;
        }
        this.setState({currentItem: {}, showCategory: data, hasChanged: false, copyExpenseStatus: false}, () => {
          if(!isValidDelete && key) {
            this.onSelect([key], data);
          }
        });
      }
    };
    if (item.isCategory && item.children.length > 0) {
      Modal.warning({
        title: messages('expense-6.key8')/*删除前请先移动该大类下的费用类型*/
      });
    } else if (item.isCategory) {
      if (item.expenseTypeCategoryOID) {
        confirm({
          title: messages('expense-6.key224')/*确认删除*/,
          okText: messages('expense-6.key291')/*确认*/,
          okCancelText: messages('common.cancel')/*取消*/,
          onOk: () =>  {
            let deleteCategoryOIDMap = this.state.deleteCategoryOIDMap;
            deleteCategoryOIDMap[item.expenseTypeCategoryOID] = true;
            this.setState({deleteCategoryOIDMap});
            expenseTypeService.deleteCategory(item.expenseTypeCategoryOID)
              .then(() => {
                message.success(messages('common.delete.success',{arg1: ''})/*{arg1} 删除成功*/);
                successHandle();
                deleteCategoryOIDMap[item.expenseTypeCategoryOID] = false;
                this.setState({deleteCategoryOIDMap});
              })
              .catch((error) => {
                deleteCategoryOIDMap[item.expenseTypeCategoryOID] = false;
                this.setState({deleteCategoryOIDMap});
                errorMessage(error.response);
              });
          },
          onCancel: () => {
            // reject('1');
          },
        });
      } else {
        successHandle();
      }
    } else {
      successHandle();
    }
  };
  saveCategoryToServer = () => {
    const { expenseTypeSetOfBooks, expenseTypeSetOfBooks: { expenseTypeLevelCode } } = this.props;
    let {currentItem, categoryName, categoryNameI18n, sourceCategory} = this.state;
    let service = expenseTypeService.editCategory;
    let params = JSON.parse(JSON.stringify(currentItem));
    let currentCategory = '';
    if (!currentItem.id) {
      params.enabled = true;
      params.setOfBooksId = expenseTypeLevelCode === 'TENANT' ? undefined : expenseTypeSetOfBooks.id;
      params.levelCode = expenseTypeLevelCode;
      service = expenseTypeService.createCategory;
    } else {
      currentCategory = sourceCategory.filter(category => category.id === currentItem.id)[0];
      params = JSON.parse(JSON.stringify(currentCategory));
    }
    params.name = categoryName;
    params.i18n = {
      name: categoryNameI18n
    };
    this.setState({saveCategoryLoading: true});
    service(params)
      .then(() => {
        message.success(messages('common.operate.success')/*操作成功*/);
        this.setState({saveCategoryLoading: false, currentItem: {}, hasChanged: false, ignoreExpandedKeys: true}, () => {
          this.getSourceCategory({});
        });
      })
      .catch(error => {
        errorMessage(error.response);
        this.setState({saveCategoryLoading: false});
      });
  };
  saveCategoryHandle = () => {
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (!err) {
        this.saveCategoryToServer();
      } else {
        message.error(messages('common.please.enter')/*请输入*/);
      }
    })
  };
  // 大类没有复制功能。 默认有添加 大类有id才能删除功能 未保存的只有删除功能
  // 详细费用类型有复制功能 未保存的只有删除功能
  renderItemButton = (item) => {
    let copyClassName = 'node-icon-wrap';
    if (!item.isAbleToCreatedManually) {
      copyClassName += ' node-disable-wrap';
    }
    return (<div className='node-right-con'>
      {!item.isNewCreate && (<Popover content={messages('common.add')/*添加*/}>
        <div className='node-icon-wrap' onClick={(e) => {
          e.stopPropagation();
          this.addHandle(item);
        }}>
          <img src={iconAdd} alt="" className='node-icon icon-add' />
          <img src={iconAddHover} alt="" className='node-icon icon-add node-icon-hover' />
        </div>
      </Popover>)}
      {!item.isNewCreate && !item.isCategory && (<Popover content={messages('common.copy')/*复制*/}>
         <div className={copyClassName} onClick={(e) => {
           e.stopPropagation();
           this.copyHandle(item);
         }}>
          <img src={iconCopy} alt="" className='node-icon icon-copy' />
          <img src={iconCopyHover} alt="" className='node-icon icon-copy node-icon-hover' />
          <img src={iconCopyDisabled} alt="" className='node-icon icon-copy node-icon-disable' />
         </div>
      </Popover>)}
      {((item.isCategory && item.id) || item.isNewCreate) && (<Popover content={messages('common.delete')/*删除*/}>
        <div className='node-icon-wrap' onClick={(e) => {
          e.stopPropagation();
          this.deleteHandle(item);
        }}>
          <img src={iconDelete} alt="" className='node-icon icon-delete' />
          <img src={iconDeleteHover} alt="" className='node-icon icon-delete node-icon-hover' />
        </div>
      </Popover>)}
    </div>);
  };
  /**
   * 右侧信息显示处理
   *  选中/hover 显示按钮信息
   *  默认费用类型显示状态信息
   * @param item
   * @returns {*}
   */
  renderRightCon = (item) => {
    const {sortCategoryStatus, batchEnableStatus} = this.state;
    let statusConClassName = 'node-right-con status-con';
    if (sortCategoryStatus || batchEnableStatus) {
      statusConClassName += ' show-status'
    }
    // 选中则显示按钮操作信息
    if (item.isCategory) {
      let deleteCategoryOIDMap = this.state.deleteCategoryOIDMap;
      if (sortCategoryStatus || batchEnableStatus) {
        return '';
      } else if (deleteCategoryOIDMap[item.expenseTypeCategoryOID]) {
        return (<div className='node-right-con'>
          <Spin/>
        </div>)
      } else {
        return this.renderItemButton(item);
      }
    } else {
      return (
        <span>
          {!sortCategoryStatus && !batchEnableStatus && this.renderItemButton(item)}
          <div className={statusConClassName}>
            <span className={item.enabled ? 'label' : 'label disable-label'}/>
            <span>{item.enabled ? messages('expense-6.key292')/*已启用*/ : messages('common.disabling')/*已禁用*/}</span>
          </div>
        </span>
      );
    }
  };
  /**
   * 树节点图标
   * 目录需区分开启和关闭
   * 费用类型则直接读取小图标
   * @param item
   * @returns {*}
   */
  renderNodeIcon = (item) => {
    let {expandedKeys} = this.state;
    if (!item.isCategory) {
      return (<img src={item.iconURL || defaultExpenseTypeIcon} alt="" className='icon-node'/>);
    }
    if (item.isCategory && expandedKeys.includes(item.key)) {
      return (<img src={iconCategoryOpen} alt="" className='category-icon-node'/>);
    } else {
      return (<img src={iconCategory} alt="" className='category-icon-node'/>);
    }
  };
  renderTitle = (item) => {
    let className = '';
    let {sortCategoryStatus} = this.state;
    if (item.isNewCreate) {
      className = 'text-create';
    }
    let content = item.title;
    if (!content) {
      content = messages('expense-6.key293')/*未保存*/;
    } else if (item.isCategory) {
      content += `(${this.getCurrentObjValue(item, 'children.length') || 0})`;
    }
    return (
      <div className={className + ' custom-node-wrap'}>
        {this.renderNodeIcon(item)}
        <p className={className + ' text-wrap'}>
          {!sortCategoryStatus ? (<Popover content={content}>
            <span className='text-title'>
              {content}
            </span>
          </Popover>) : ( <span className='text-title'>{content}</span>)}
          {item.isNewCreate && !item.expenseTypeId &&
          <span className='normal-text'>{messages('expense-6.key294')/*请在右边填写内容*/}</span>}
        </p>
        {this.renderRightCon(item)}
      </div>
    );
  };
  renderTree = (data) => {
    return data.map(item => {
      if (item.children && item.children.length) {
        return (
          <TreeNode key={item.key} title={this.renderTitle(item)} isLeaf={!item.isCategory}>
            {this.renderTree(item.children)}
          </TreeNode>
        );
      }
      return (
        <TreeNode key={item.key} title={this.renderTitle(item)}/>
      );
    });
  };
  // 保存费用 前端保存 保存完后获取当前的信息 替换即可 不需要重新刷数据
  onSaveExpense = (id) => {
    this.setState({
      hasChanged: false,
      currentItem: {key: id},
      ignoreExpandedKeys: true,
      copyExpenseStatus: false
    }, () => {
      this.getSourceCategory({});
    });
  };
  getTreeConClassName = () => {
    const {searchExpense, batchEnableStatus, sortCategoryStatus} = this.state;
    let className = 'left-con-content';
    if (searchExpense) {
      className += ' has-search'
    }
    if (batchEnableStatus) {
      className += ' has-sub-footer'
    }
    if (sortCategoryStatus) {
      className += ' sort-con'
    }
    return className;
  };
  getLeftConClassName = () => {
    const {leftPutWay, leftPutWayEnd} = this.state;
    let className = 'left-con';
    if (leftPutWay) {
      className += ' left-put-way'
    }
    if (leftPutWayEnd) {
      className += ' left-put-way-end'
    }
    return className;
  };
  // 手动触发回报修改信息
  setHasChange = (value) => {
    this.setState({hasChanged: value});
  };
  render() {
    const { authPolicyAll } = this.props;
    const {
      showCategory, expandedKeys, setOfBooksLoading, setOfBooks, expenseTypeId, mod,
      categoryName, categoryNameI18n, enableEditCategoryName, loading, sortCategoryStatus,
      selectedKeys, copyExpenseStatus, leftPutWay, batchEnableStatus, showEnableExpense,
      saveCategoryLoading, batchEnableLoading, sureSortLoading, checkedAll,
      checkedKeys, leftPutWayEnd, hasChanged
    } = this.state;
    const {getFieldDecorator} = this.props.form;
    let formItemLayout = {
      labelCol: {span: 8},
      wrapperCol: {span: 8},
    };
    return (
      <div className="expense-type-v2-wrap">
        {(batchEnableStatus || sortCategoryStatus) && (<div className='expense-type-mask' />)}
        <div className="expense-type-v2">
          <div className={this.getLeftConClassName()}>
            {!batchEnableStatus && !sortCategoryStatus && (<div className="left-con-header">
              {
                setOfBooksLoading
                  ? <Spin/>
                  : <ExpenseSearchForm
                    putAway={leftPutWay}
                    setOfBooks={setOfBooks}
                    handleHide={this.handleHide}
                    handlePutAway={this.handlePutAway}
                    setOfBooksChange={this.handleChangeSetOfBooks}/>
              }
            </div>)}
            {
              leftPutWayEnd && !batchEnableStatus && !sortCategoryStatus && (<div className='put-way-con-warp'>
                <Dropdown overlay={this.renderExportMenu()}>
                  <Button className='icon-export-wrap button-wrap'>
                    <img src={iconExport} alt="" className='icon-button'/>
                  </Button>
                </Dropdown>
                {this.renderImporter(true)}
                <Popover placement="rightTop"
                         overlayClassName={'shrink-con-wrap'}
                         content={(<div>
                      <Tree className="draggable-tree ant-tree-block-node"
                            selectedKeys={selectedKeys}
                            defaultExpandedKeys={expandedKeys}
                            onSelect={this.onSelect}
                            onDrop={this.onDrop}>
                        {this.renderTree(showCategory)}
                      </Tree>
                    </div>)}>
                  <Button className='add-button-custom button-wrap'>
                    <img src={iconCategoryShrink} alt="" className='icon-button'/>
                  </Button>
                </Popover>
                <Popover content={messages('expense-6.key295')/*新建费用类型*/}>
                  <Button onClick={() => this.addHandle({})}
                          className='add-button-custom button-wrap'>
                    <img src={iconAddBlack} alt="" className='icon-button'/>
                  </Button>
                </Popover>
              </div>)
            }
            {!leftPutWayEnd && !batchEnableStatus && !sortCategoryStatus && authPolicyAll && (<div className="button-group">
              <Popover content={messages('expense-6.key296')/*新建分组*/}>
                <Button onClick={() => this.addHandle({isCategory: true})} type="primary"
                        className='add-button-custom'>
                  <img src={iconAddCategory} alt="" className='icon-button'/><span>{messages('expense-6.key32')/*分组*/}</span>
                </Button>
              </Popover>
              <Popover content={messages('expense-6.key295')/*新建费用类型*/}>
                <Button onClick={() => this.addHandle({})} type="primary"
                        className='add-button-custom'>
                  <img src={iconAddWhite} alt="" className='icon-button'/><span>{messages('expense-6.key15')/*类型*/}</span>
                </Button>
              </Popover>
              {this.renderImporter()}
              <Dropdown overlay={this.renderExportMenu()}>
                <Button className='icon-export-wrap'>
                  <img src={iconExport} alt="" className='icon-button'/>
                  <img src={iconArrowExport} alt="" className='icon-button icon-arrow-export'/>
                  <img src={iconArrowExportHover} alt="" className='icon-button icon-arrow-export icon-arrow-hover'/>
                </Button>
              </Dropdown>
            </div>)}
            {!leftPutWayEnd && !batchEnableStatus && !sortCategoryStatus && (
              <Checkbox checked={showEnableExpense}
                        onChange={this.onShowEnableChange}
                        style={{
                          display: 'block',
                          textAlign: 'left',
                          paddingRight: '8px'
                        }}>
                {messages('expense-6.key297')/*显示禁用的费用类型*/}
              </Checkbox>
            )}
            {!leftPutWayEnd && (
              <div className={this.getTreeConClassName()}>
                {loading && (<div className='tree-loading-wrap'>
                  <Spin/>
                </div>)}
                {batchEnableStatus && (
                  <Checkbox checked={checkedAll}
                            style={{marginLeft: '6px'}}
                            onChange={this.onCheckedAllChange}>
                    {messages('expense-6.key298')/*全选*/}
                  </Checkbox>
                )}
                <Tree className="draggable-tree ant-tree-block-node"
                      draggable={sortCategoryStatus}
                      checkable={batchEnableStatus}
                      selectedKeys={selectedKeys}
                      expandedKeys={expandedKeys}
                      checkedKeys={checkedKeys}
                      onSelect={this.onSelect}
                      onExpand={this.onExpand}
                      onCheck={this.onCheck}
                      onDrop={this.onDrop}>
                  {this.renderTree(showCategory)}
                </Tree>
              </div>)}
            {!leftPutWay && (<div className={batchEnableStatus? 'page-footer has-sub-tip': 'page-footer'}>
              {!batchEnableStatus && !sortCategoryStatus && (<Button onClick={this.handleBatchEnable}>
                {messages('expense-6.key299')/*批量启用/禁用*/}
              </Button>)}
              {!batchEnableStatus && !sortCategoryStatus && (<Button onClick={this.handleSortCategory}>
                {messages('expense-6.key300')/*费用排序*/}
              </Button>)}
              {batchEnableStatus && (<div>
                <p className='third-title'>{messages('expense-6.key301',{arg1: this.getValidCheckedKeys(false,true).length})/*已选{arg1}条*/}</p>
                <span>
                  <Button onClick={() => this.handleBatchEnableExpense(true)} loading={batchEnableLoading}>
                    {messages('common.status.enable')/*启用temp*/}
                  </Button>
                  <Button onClick={() => this.handleBatchEnableExpense(false)} loading={batchEnableLoading}>
                    {messages('common.status.disable')/*禁用temp*/}
                  </Button>
                  <Button onClick={this.cancelBatchEnable}>
                    {messages('common.back')/*返回*/}
                  </Button>
                </span>
              </div>)}
              {sortCategoryStatus && (<span>
                <Button onClick={this.sureSortHandle} type="primary" loading={sureSortLoading}>
                  {messages('expense-6.key12')/*完成*/}
                </Button>
                <Button onClick={this.cancelSortHandle}>
                  {messages('common.cancel')/*取消*/}
                </Button>
              </span>)}
            </div>)}
          </div>
          {mod === 'CATEGORY' && (
            <div className="right-con">
              <div className='right-con-content'>
                <div className='right-con-header second-title'>{messages('expense-6.key302')/*费用分组命名*/}</div>
                <Form onSubmit={this.handleSave} className='new-form'>
                  <FormItem label={messages('expense-6.key303')/*分组名称*/} {...formItemLayout}>
                    {getFieldDecorator('categoryName', {
                      rules: [{
                        required: true, message: messages('common.please.enter')/*请输入*/,
                      }],
                      initialValue: categoryName
                    })(
                      <LanguageInput name={categoryName}
                                     i18nName={categoryNameI18n}
                                     nameChange={(value, i18n) => this.handleChangeI18n(value, i18n, 'categoryName')}
                                     inpRule={[{
                                       length: 30,
                                       language: 'zh_cn'
                                     }, {
                                       length: 100,
                                       language: 'en'
                                     }]}
                                     isEdit={true}
                                     disabled={!authPolicyAll || !enableEditCategoryName}
                      />
                    )}
                  </FormItem>
                </Form>
              </div>
              <div className="page-footer">
                <Button onClick={this.saveCategoryHandle} type="primary" loading={saveCategoryLoading}>
                  {messages('common.save')/*保存*/}
                </Button>
              </div>
            </div>
          )}
          {mod === 'EXPENSE_DETAIL' && (
            <NewExpenseType params={{expenseTypeId: expenseTypeId, copy: copyExpenseStatus}}
                            handlePutAway={this.handlePutAway}
                            putAway={leftPutWay}
                            modalRef={ref => this.expenseTypeRef = ref}
                            hasChanged={hasChanged}
                            setHasChange={this.setHasChange}
                            onSave={this.onSaveExpense}/>
          )}
        </div>
      </div>
    );
  }
}

ExpenseTypeV2.contextTypes = {
  router: React.PropTypes.object
};

function mapStateToProps(state) {
  return {
    tenant: state.login.tenant,
    company: state.login.company,
    authPolicyAll: state.main.authPolicyAll,
    expenseTypeSetOfBooks: state.setting.expenseTypeSetOfBooks,
    currentMenuPermission: state.main.currentMenuPermission
  };
}


const wrappedExpenseTypeV2 = Form.create()(ExpenseTypeV2);

export default connect(mapStateToProps)(wrappedExpenseTypeV2);
